package com.xyzboom.database.dao;

import com.xyzboom.database.entity.HitCourse;
import com.xyzboom.database.utils.DatabaseUtils;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.AbstractListHandler;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;

public class HitCourseDAO {
    private static ResultSetHandler<HitCourse> getHandler() {
        return rs -> {
            if (rs.next()) {
                return new HitCourse(
                        rs.getInt("uId"),
                        rs.getString("uName"),
                        rs.getInt("cId"),
                        rs.getString("cName"),
                        rs.getInt("score")
                );
            }
            return null;
        };
    }

    private static AbstractListHandler<HitCourse> getListHandler() {
        return new AbstractListHandler<HitCourse>() {
            @Override
            protected HitCourse handleRow(ResultSet rs) throws SQLException {
                return new HitCourse(
                        rs.getInt("uId"),
                        rs.getString("uName"),
                        rs.getInt("cId"),
                        rs.getString("cName"),
                        rs.getInt("score")
                );
            }
        };
    }

    public static int addHitCourses(int uId, List<Integer> cIds) throws SQLException {
        Object[][] params = getParams(uId, cIds);
        int[] result = DatabaseUtils.getQueryRunner().batch(
                "insert into hitcourse (uId, cId, score)" +
                        "VALUES (?, ?, null);", params);
        return Arrays.stream(result).sum();
    }

    private static Object[][] getParams(int uId, List<Integer> cIds) {
        Object[][] params = new Object[cIds.size()][];
        for (int i = 0; i < cIds.size(); i++) {
//            System.out.println(uId + " " + cIds.get(i));
            params[i] = new Object[]{uId, cIds.get(i)};
        }
        return params;
    }

    public static List<HitCourse>
    getHitCourses(int uId) throws SQLException {
        return getHitCourses(uId, HitCourse.HitCourseColumn.NULL, false);
    }

    public static List<HitCourse>
    getHitCourses(int uId, HitCourse.HitCourseColumn orderBy) throws SQLException {
        return getHitCourses(uId, orderBy, false);
    }

    public static List<HitCourse>
    getHitCourses(int uId, HitCourse.HitCourseColumn orderBy, boolean descend) throws SQLException {
        StringBuilder sb = new StringBuilder();
        if (orderBy == HitCourse.HitCourseColumn.NULL) {
            sb.append(HitCourse.HitCourseColumn.UID);
        } else {
            sb.append(orderBy.value);
        }
        if (descend) {
            sb.append(" desc");
        }
        return DatabaseUtils.getQueryRunner().query(
                "SELECT uId,uName,cId,cName,score\n" +
                        "FROM user\n" +
                        "    natural join hitcourse\n" +
                        "    natural join course\n" +
                        "WHERE uId=? order by ?",
                getListHandler(), uId, sb.toString());
    }

    public static HitCourse getHitCourse(int uId, int cId) throws SQLException {
        return DatabaseUtils.getQueryRunner().query(
                "SELECT uId,uName,cId,cName,score\n" +
                        "FROM user\n" +
                        "    natural join hitcourse\n" +
                        "    natural join course\n" +
                        "WHERE uId=? and cId=?",
                getHandler(), uId, cId);
    }

    public static boolean hitCourseExists(int uId, int cId) throws SQLException {
        return getHitCourse(uId, cId) != null;
    }

    public static int removeHitCourse(int uId, List<Integer> cIds) throws SQLException {
        Object[][] params = getParams(uId, cIds);
        int[] result = DatabaseUtils.getQueryRunner().batch(
                "delete from hitcourse where uId = ? and cId = ?", params);
        return Arrays.stream(result).sum();
    }
}
